'''
Created on Aug 17, 2010

@author: dexen
'''
'''
Created on 30-Jul-2010

@author: dexen
'''


import os
import sys
import random

import daysimfunc
from pybim_houdini import IdfGeom, IdfShade, IdfWindow, IdfZone, IdfZoneSurface, RadGeom, RadSurface 


#THE CLASS WAS WRITTEN ASSUMING ALL THE POINTS ARE COMING IN ANTI-CLOCKWISE ARRANGEMENT WITH NORMAL POINTING OUTWARDS

ROOT = "/home/dexen/workspace/overhang_schema"
def source_houdini_setup():
    curdir = os.getcwd()
    dir = "/opt/hfs11.0.469"
    os.chdir(dir)
    os.system(".  houdini_setup")
    os.chdir(curdir)
    
    
def enableHouModule():
    '''Set up the environment so that "import hou" works.'''
    # Importing hou will load in Houdini's libraries and initialize Houdini.
    # In turn, Houdini will load any HDK extensions written in C++.  These
    # extensions need to link against Houdini's libraries, so we need to
    # make sure that the symbols from Houdini's libraries are visible to
    # other libraries that Houdini loads.  So, we adjust Python's dlopen
    # flags before importing hou.
    if hasattr(sys, "setdlopenflags"):
        old_dlopen_flags = sys.getdlopenflags()
        import DLFCN
        sys.setdlopenflags(old_dlopen_flags | DLFCN.RTLD_GLOBAL)

    try:
        import hou
    except ImportError:
        # Add $HFS/houdini/python2.5libs to sys.path so Python can find the
        # hou module.
        sys.path.append( os.environ['HFS'] + "/houdini/python%d.%dlibs" % sys.version_info[:2])
        import hou
    finally:
        if hasattr(sys, "setdlopenflags"):
            sys.setdlopenflags(old_dlopen_flags)
            
def get_points_from_prim(prim):
    verts = prim.vertices()
    points = []
    for vert in verts:
        points.append(vert.point().position())
    return points
def rearrange(point_list):
    arranged =  []
    for point in point_list:
        arranged_pt = [point[0], -point[2], point[1]]
        arranged.append(arranged_pt)
    return arranged

def houdini(variables, basefilepath):
    #source_houdini_setup()
    enableHouModule()
    import hou
    hou.hipFile.load(basefilepath)
    phenotype = hou.node("/obj/geo1/phenotype")
    phenotype.setParms({"length": variables[0], "height": variables[1], 
                        "rotation": variables[2], "wall_mat": variables[3],
                        "wall_mat2": variables[4], "wall_mat3":variables[5],
                        "wall_mat4": variables[6], "shade_length": variables[7],
                        "shade_length2": variables[8], "shade_length3": variables[9],
                        "shade_length4": variables[10], "roof_mat": variables[11],
                        "flr_mat": variables[12], "roof_slope": variables[13]})
    #CREATE OBJECT 
    idf_geom = IdfGeom()
    zone1 = IdfZone("zone1", idf_geom)
    rad_geom = RadGeom()
    #FOR ENERGYPLUS SURFACE
    srfs = hou.node("/obj/geo1/merge_surfaces")
    srf_prims = srfs.geometry().prims()
    for srf_prim in srf_prims:
        srf_point = get_points_from_prim(srf_prim)
        a_srf_point = rearrange(srf_point)
        srf_name = srf_prim.attribValue("name")
        srf_mat = srf_prim.attribValue("idf_mat")
        srf_type = srf_prim.attribValue("type")
        srf = IdfZoneSurface(srf_name, a_srf_point, srf_mat, srf_type)
        zone1.add_surface(srf)
        
    #ENERGYPLUS WINDOW
    windows = hou.node("/obj/geo1/foreach_window")
    win_prims = windows.geometry().prims()
    for win_prim in win_prims:
        win_point = get_points_from_prim(win_prim)
        a_win_point = rearrange(win_point)
        win_name = win_prim.attribValue("name")
        win_mat = win_prim.attribValue("idf_mat")
        win_host = win_prim.attribValue("host")
        win = IdfWindow(win_name, a_win_point, win_mat, win_host)
        zone1.add_window(win)
        
    #ENERGYPLUS SHADE
    shade = hou.node("/obj/geo1/delete3_shade")
    shade_prims = shade.geometry().prims()
    for shade_prim in shade_prims:
        shade_point = get_points_from_prim(shade_prim)
        a_shade_point = rearrange(shade_point)
        shade_name = shade_prim.attribValue("name")
        shade_host = shade_prim.attribValue("host")
        shade = IdfShade(shade_name, a_shade_point,None, shade_host)
        zone1.add_shade(shade)
        
    #FOR RADIANCE
    rad_srfs = hou.node("/obj/geo1/merge_radsurface")
    rad_srf_prims = rad_srfs.geometry().prims()
    for rad_srf_prim in rad_srf_prims:
        rad_srfpoint = get_points_from_prim(rad_srf_prim)
        a_rad_srfpoint = rearrange(rad_srfpoint)
        rad_srfname = rad_srf_prim.attribValue("name")
        rad_srfmat = rad_srf_prim.attribValue("rad_mat")
        RadSurface(rad_srfname, a_rad_srfpoint, rad_srfmat, rad_geom)
        
    #SENSOR POINTS 
    sensor_pts = hou.node("/obj/geo1/sensor_pts").geometry().points()
    pt_list = []
    for pt in sensor_pts:
        position = pt.position()
        pt_list.append(position)
    rad_geom.add_sensor_points(rearrange(pt_list), "0 0 1")

    #COST FACTOR
    sgl_glazes = hou.node("/obj/geo1/measure_sglglaze").geometry().prims()
    total_sgl = []
    for sgl_glaze in sgl_glazes:
        sgl_area = sgl_glaze.attribValue("area")
        total_sgl.append(sgl_area)
    total_sgl_area = sum(total_sgl)
    sgl_cost = total_sgl_area*2
    
    dbl_glazes = hou.node("/obj/geo1/measure_dblglaze").geometry().prims()
    total_dbl = []
    for dbl_glaze in dbl_glazes:
        dbl_area = dbl_glaze.attribValue("area")
        total_dbl.append(dbl_area)
    total_dbl_area = sum(total_dbl)
    dbl_cost = total_dbl_area*2.5
    
    lights = hou.node("/obj/geo1/switch_light").geometry().prims()
    total_light = []
    for light in lights:
        light_area = light.attribValue("area")
        total_light.append(light_area)
    total_light_area = sum(total_light)
    light_cost = total_light_area*1
    
    heavys = hou.node("/obj/geo1/switch_heavy").geometry().prims()
    total_heavy = []
    for heavy in heavys:
        heavy_area = heavy.attribValue("area")
        total_heavy.append(heavy_area)
    total_heavy_area = sum(total_heavy)
    heavy_cost = total_heavy_area*1.5
    cost_factor = dbl_cost + light_cost + sgl_cost + heavy_cost

    hou.node("/obj/geo1/file1").geometry().saveToFile("overhangschema.bgeo")
 
    
    return rad_geom, idf_geom, cost_factor

def render(hou_render_path):
    enableHouModule()
    import hou
    hou.hipFile.load(hou_render_path)
    hou.node("/out/mantra_perspective1").render()
    hou.node("/img/comp1/rop_comp1").render()

#--------------------------------------------------------------------------------
#function for generating random height and width
def gmap(gene, values):
    step = 1.0 / len(values)
    for i in range(len(values)):
        if gene < (step + i*step):
            return values[i]
        
#---------------------------------------------------------------------------------
def random_genotype(size):
    genotype = []
    for _ in range(size):
        genotype.append(random.random())
    return genotype
#--------------------------------------------------------------------------------
def map_genotype(genotype):
    # 1st gene is length (width is dependent on lenght due to constant area)
    # 2nd gene is the height
    # 3rd gene is rotation
    # 4th to 7th genes are wall materials (0 to 4) 
    # 8th to 11th genes are shade lengths between 0 and 2
    # 12th gene is roof material 
    # 13th gene is floor material 
    # 14th gene is rf slope 
    building_length = range(8, 29)
    building_heights = [2.5, 3, 3.5, 4, 4.5, 5]
    rotation = range(0,360, 10)
    wall_mat = range(0, 4)
    roof_mat = [0,1]
    flr_mat = [0,1]
    slope = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1]
    variables = []
    variables.append(gmap(genotype[0] ,  building_length))
    variables.append(gmap(genotype[1] ,  building_heights))
    variables.append(gmap(genotype[2] ,  rotation))
    
    for i in range(3, 7):
        variables.append(gmap(genotype[i], wall_mat))
                         
    for i in range(7, 11):
        variables.append(round ((genotype[i]* 2), 1))
    
    variables.append(gmap(genotype[11] ,  roof_mat))
    variables.append(gmap(genotype[12] ,  flr_mat))
    variables.append(gmap(genotype[13] ,  slope))
    
    return variables
#--------------------------------------------------------------------------------

def develop(genotype):
    variables = map_genotype(genotype)
    print variables
    basefilepath = os.path.join(ROOT, "houdinibasefile", "overhangschema.hipnc")
    data = houdini(variables, basefilepath)
    return data
    
def eval_energy(data):
    path = os.path.join(ROOT, "energyplusbasefile")
    filename  = "overhangschema"
    idf = data[1]
    idf.execute_idf(path, filename)
    result = idf.eval_idf("energytransfer")
    return result
    
def eval_daylight(data):
    rad_path = os.path.join(ROOT,"radiancebasefile")
    filename  = "overhangschema"
    rad = data[0]
    rad.create_rad(rad_path, filename)
    
    hea_path = os.path.join(ROOT, "daysimbasefile")
    hea_bin_dir = "/home/dexen/daysim/bin/"
    rad.execute_hea(hea_path, filename, hea_bin_dir)
    result = rad.eval_hea()
    average = sum(result)/(len(result))
    return average

def eval_daylight_rad(data):
    rad_path = os.path.join(ROOT,"radiancebasefile")
    filename  = "overhangschema"
    rad = data[0]
    rad.execute_rad(rad_path, filename)
    result = rad.eval_rad("illuminance")
    average = sum(result)/(len(result))
    return average

def setup():
    weather_file = "SGP_Singapore.486980_IWEC"
    source_file =  '/home/dexen/daysim/wea/' + weather_file + '.epw'
    destination_file = '/home/dexen/daysim/wea/' + weather_file + '_60min.wea'
    bin_dir = "/home/dexen/daysim/bin"
    daysimfunc.execute_epw2wea(bin_dir, source_file, destination_file)

def write_results(results):
    result_filepath = os.path.join(ROOT, "overallresult")
    if not os.path.isdir(result_filepath):
        os.mkdir(result_filepath)
    prevdir = os.getcwd()
    os.chdir(result_filepath)
    result_file = open("finalresult.csv",  "w")
    #write the results into a csv file 
    result_file.write("project_id,daylight_autonomy(%),total_energy_transfer(kWh)(daily_avg),costfactor\n")
    result_file.write(results)
    result_file.close()
    os.chdir(prevdir)
#--------------------------------------------------------------------------------
# MAIN SCRIPT
#--------------------------------------------------------------------------------
random.seed()
#CONVERT EPW TO WEA
#setup()

num_of_design = 1
results = ""
for counter in range(num_of_design):
    #generate the variables for the developmental script
    #genotype = random_genotype(14)
    #developmental script
    genotype = [0.86861733103862393, 0.031176715593669413, 0.19852431194791975, 0.87652806087684298, 0.88977421808561585, 0.40409178024831727, 0.67714396216905559, 0.0090937031214193276, 0.71888857267347184, 0.99588266947451265, 0.0091995370440903779, 0.15570945079472454, 0.3954633071069823, 0.060050839521182509]
    #genotype = [0.3532284351809154, 0.042028840841427884, 0.5845324315730388, 0.31469554006517408, 0.99582559983698005, 0.36503690412274659, 0.613408379413377, 0.076320427084984654, 0.38768355926602804, 0.6643392361381173, 0.75528301694507072, 0.49754213140348891, 0.16017037603590911, 0.4775630248144066]
    rad_idf_data = develop(genotype)
    #evaluation
    daylight = eval_daylight_rad(rad_idf_data)
    energy = eval_energy(rad_idf_data)
    cost = str(rad_idf_data[2])
    results = results + str(counter) + ","+ str(daylight) + "," +  str(energy) + "," +  cost +"\n" 
    #render
    #hou_render_path = os.path.join( ROOT, "houdinibasefile", "overhangschema_render.hipnc")  
    #render(hou_render_path)
    print "done"
    
#write the results into a csv file 
write_results(results)
print "FINISH "







